//
// Created by gogoqiu on 2022/1/11.
//

#include "MainApp.h"
// wxWidgets
#include "wx/wx.h"
#include "wx/confbase.h"
#include "wx/stdpaths.h"
#include "wx/sysopt.h"
#include <wx/fs_zip.h> // ZIP filesystem support
#include <wx/tipdlg.h>
#include <wx/cshelp.h>
#include <wx/image.h>

// svncpp
#include "svncpp/wc.hpp"

//app
//#include "config.hpp"
//#include "hist_mgr.hpp"
#include "MainDialog.h"
#include "preferences.hpp"
//#include "version.hpp"

static const wxChar HELP_FILE[] =  wxT ( "/Resources/HelpFile" );

#ifdef USE_STARTUP_TIPS
static const wxChar TIPS_FILE[] = wxT ( "/Resources/TipsFile" );
static const wxChar TIPS_SHOW_AT_STARTUP[] = wxT ( "/Main/TipsShowAtStartup" );
static const wxChar TIPS_LAST_INDEX[] = wxT ( "/Main/TipsLastIndex" );
#endif

IMPLEMENT_APP ( MainApp )

#define APPLICATION_NAME wxT("RapidSVN")

/*
 *
 */
bool MainApp::OnInit()
{
    // application and vendor name are used by wxConfig to construct the name
    // of the config file/registry key and must be set before the first call
    // to Get() if you want to override the default values (the application
    // name is the name of the executable and the vendor name is the same)
    SetVendorName ( APPLICATION_NAME );
    SetAppName ( APPLICATION_NAME );
    //
    this->tag = APPLICATION_NAME;
    /*
     * SqlitePreferenceStorage::Load()
     *
     */
    //this->setPreferenceCore( new MyPreferenceCore( this ));
    //get core
    setPreferenceCore( new MyPreferenceCore( this ) );
    /*
     * load all preferences from storage
     * and filter with the app tag
     */
    mPreferenceCore->adapter();

    m_locale.Init();
    wxLocale::AddCatalogLookupPathPrefix ( wxT ( "locale" ) );
#ifdef __WXMAC__
    wxSystemOptions::SetOption ( wxT ( "mac.listctrl.always_use_generic" ), true );
	m_locale.AddCatalogLookupPathPrefix (
	    wxStandardPaths::Get().GetResourcesDir() +
	    wxFileName::GetPathSeparator() +
	    wxT ( "locale" ) );
#endif //__WXMAC__
    m_locale.AddCatalog ( wxT ( "rapidsvn" ) );

    // Add support for PNG
    wxImage::AddHandler ( new wxPNGHandler );

    // Add support for SVN_ASP_DOT_NET_HACK
    if ( wxGetEnv ( wxT ( "SVN_ASP_DOT_NET_HACK" ), nullptr ) )
        svn::Wc::setAdmDir ( "_svn" );

#ifdef _WIN32
    // Avoiding to conflict with different versioned apr-iconv.
	wxString apr_iconv_path;
	if ( wxGetEnv ( wxT ( "APR_ICONV_PATH" ), &apr_iconv_path ) ) {
		wxSetEnv ( wxT ( "__SAVED_APR_ICONV_PATH" ), apr_iconv_path.c_str() );
		wxSetEnv ( wxT ( "APR_ICONV_PATH" ), wxStandardPaths::Get().GetDataDir() + wxT ( "\\iconv" ) );
	}
#endif

#ifdef  USE_HTML_HELP
    // Initialise the HTML help
	wxFileSystem::AddHandler ( new wxZipFSHandler );
	m_helpController = new wxHtmlHelpController;
	m_helpController->SetTitleFormat ( _ ( "RapidSVN Help: %s" ) );
	LocateHelp();

	// Initialise a popup-help-text provider system, connected to the main help system
	wxHelpControllerHelpProvider* provider = new wxHelpControllerHelpProvider;
	provider->SetHelpController ( m_helpController );
#else
    auto* provider = new wxSimpleHelpProvider;
#endif
    wxHelpProvider::Set ( provider );
    //
    auto * frame = new MainDialog ( this, APPLICATION_NAME, m_locale );
    frame->Show ( TRUE );
    SetTopWindow ( frame );

    // Show tips if configured
#ifdef USE_STARTUP_TIPS
    wxTipProvider* tipProvider = MakeTipProvider();
	if ( tipProvider ) {
		bool showAtStartup = wxShowTip ( frame, tipProvider );
		SaveTipsInfo ( showAtStartup, tipProvider->GetCurrentTip() );
		delete tipProvider;
	}
#endif

    return TRUE;
}

int MainApp::OnExit()
{
    OptionallyPurgeTempFiles();

    //TheHistoryManager.Cleanup();

    // destroy application configuration object
    delete wxConfigBase::Set ( ( wxConfigBase * ) nullptr );

    // Remove the help provider & close down help
    delete wxHelpProvider::Set ( nullptr );
#ifdef  USE_HTML_HELP
    delete m_helpController;
#endif

    return 0;
}

void MainApp::OptionallyRegisterTempFile ( const wxString & filename )
{
    Preferences preferences;

    if ( preferences.purgeTempFiles ) {
        m_TempFiles.Add ( filename );
    } else {
        m_TempFiles.Clear();
    }
}

void MainApp::OptionallyPurgeTempFiles()
{
    Preferences preferences;

    if ( preferences.purgeTempFiles ) {
        for ( size_t i = 0; i < m_TempFiles.GetCount(); ++i ) {
            ::wxRemoveFile ( m_TempFiles.Item ( i ) );
        }
    }
    m_TempFiles.Clear();
}

#ifdef  USE_HTML_HELP
bool RapidSvnApp::LocateHelp()
{
	wxString appPath = wxFileName ( argv[0] ).GetPath ( wxPATH_GET_VOLUME );
	if ( appPath.IsEmpty() )
		appPath = wxGetCwd();
	wxString appName = wxFileName ( argv[0] ).GetName();
#ifdef __WXMAC__
	appPath += appName + wxT ( ".app/Contents/Resources" ) );
#endif

	wxString helpfile = appPath + wxFileName::GetPathSeparator() + appName + wxT ( ".htb" );
	wxConfigBase* cfg = wxConfigBase::Get();
	helpfile = cfg->Read ( HELP_FILE, helpfile );
	if ( helpfile.IsEmpty() ) {
		return false;
	}

	// TODO: Hmmm - I haven't called Initialise yet, but AddBook seems to work directly...
	while ( !m_helpController->AddBook ( wxFileName ( helpfile ) ) ) {
		wxFileDialog dlg ( NULL, _ ( "Locate help" ), appPath, wxEmptyString, wxT ( "*.htb" ), wxOPEN | wxFILE_MUST_EXIST );
		if ( dlg.ShowModal() == wxID_OK ) {
			helpfile = dlg.GetPath();
			cfg->Write ( HELP_FILE, helpfile );
		} else {
			if ( wxMessageBox ( _ ( "No help file was chosen, would you like to be \n" "asked again after next application start?" ), _ ( "Locate help" ), wxYES_NO | wxICON_QUESTION ) == wxYES ) {
				if ( cfg->Exists ( HELP_FILE ) ) {
					cfg->DeleteEntry ( HELP_FILE );
				}
			} else {
				helpfile = wxEmptyString;
				cfg->Write ( HELP_FILE, helpfile );
			}
			return false;
		}
	}
	return true;
}
#endif

#ifdef USE_STARTUP_TIPS
wxTipProvider*
RapidSvnApp::MakeTipProvider ( bool force )
{
	wxString appPath = wxFileName ( argv[0] ).GetPath ( wxPATH_GET_VOLUME );
	if ( appPath.IsEmpty() ) {
		appPath = wxGetCwd();
	}
	wxString appName = wxFileName ( argv[0] ).GetName();
#ifdef __WXMAC__
	appPath += appName + wxT ( ".app/Contents/Resources" ) );
#endif

	wxString tipsfile = appPath + wxFileName::GetPathSeparator() + appName + wxT ( "_tips.txt" );
	bool showTips = true;
	wxConfigBase* cfg = wxConfigBase::Get();
	cfg->Read ( TIPS_FILE, &tipsfile );
	if ( !force ) {
	cfg->Read ( TIPS_SHOW_AT_STARTUP, &showTips ) ;
		if ( tipsfile.IsEmpty() || !showTips ) {
			return NULL;
		}
	}

	int tipIndex = 0;
	cfg->Read ( TIPS_LAST_INDEX, &tipIndex );
	wxTipProvider* tipProvider = NULL;

	while ( !wxFileName ( tipsfile ).FileExists() || ( tipProvider = wxCreateFileTipProvider ( tipsfile, tipIndex ) ) == NULL ) {
		wxFileDialog dlg ( NULL, _ ( "Locate tips file" ), appPath, wxEmptyString, wxT ( "*.txt" ), wxOPEN | wxFILE_MUST_EXIST );
		if ( dlg.ShowModal() == wxID_OK ) {
			tipsfile = dlg.GetPath();
			cfg->Write ( TIPS_FILE, tipsfile );
		} else {
			if ( wxMessageBox ( _ ( "No tips file was chosen, would you like to be \n" "asked again after next application start?" ), _ ( "Locate tips" ), wxYES_NO | wxICON_QUESTION ) == wxYES ) {
				if ( cfg->Exists ( TIPS_FILE ) ) {
					cfg->DeleteEntry ( TIPS_FILE );
				}
			} else {
				tipsfile = wxEmptyString;
				cfg->Write ( TIPS_FILE, tipsfile );
			}
			return NULL;
		}
	}

	return tipProvider;
}

void RapidSvnApp::SaveTipsInfo ( bool showAtStartup, int tipIndex )
{
	wxConfigBase* cfg = wxConfigBase::Get();
	cfg->Write ( TIPS_SHOW_AT_STARTUP, showAtStartup );
	cfg->Write ( TIPS_LAST_INDEX, tipIndex );
}
#endif

/* -----------------------------------------------------------------
 * local variables:
 * eval: (load-file "../rapidsvn-dev.el")
 * end:
 */

/*
 *
 */
MyPreferenceCore::MyPreferenceCore(MyTagApp *myTagApp1)
        : PreferenceCore(myTagApp1) {
}